package sanshui.system.trade.factory.trade.strategy.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import sanshui.system.trade.factory.data.Bar;
import sanshui.system.trade.factory.trade.TradeSystemContext;
import sanshui.system.trade.factory.trade.indicator.IndicatorCode;
import sanshui.system.trade.factory.trade.indicator.IndicatorResult;
import sanshui.system.trade.factory.trade.strategy.AbstractStrategy;
import sanshui.system.trade.factory.trade.strategy.StrategyCallType;
import sanshui.system.trade.factory.trade.strategy.StrategyCode;
import sanshui.system.trade.factory.trade.strategy.StrategyResult;
import sanshui.system.trade.util.DataParseUtil;
import sanshui.system.trade.util.IndicatorUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@Component
public class M45Strategy extends AbstractStrategy {
    private static final Logger logger = LoggerFactory.getLogger(M45Strategy.class);

    @Override
    public StrategyCode getStrategyCode() {
        return StrategyCode.M45;
    }

    @Override
    public IndicatorResult execCustom(Bar bar, TradeSystemContext tradeSystemContext) {
        Map<String, List<Bar>> hisPriceDataMap = tradeSystemContext.getDataCache().getHisPriceDataMap();
        List<Bar> barList = hisPriceDataMap.get(bar.symbol);
        List<Long> hisCloses = barList.stream().map(Bar::getClose).collect(Collectors.toList());
        List<Long> hisVol = barList.stream().map(Bar::getVolume).collect(Collectors.toList());

        IndicatorResult result = new IndicatorResult();
        result.setCode(bar.getSymbol());

        Map<String, List<String>> paramMap = new HashMap<>();
        List<Long> m5 = IndicatorUtil.MAn(hisCloses, 5);
        paramMap.put("M5", DataParseUtil.parseToStringList(m5));
        List<Long> m10 = IndicatorUtil.MAn(hisCloses, 10);
        paramMap.put("M10", DataParseUtil.parseToStringList(m10));
        List<Long> m30 = IndicatorUtil.MAn(hisCloses, 30);
        paramMap.put("M30", DataParseUtil.parseToStringList(m30));
        List<Long> em5 = IndicatorUtil.EMAn(hisCloses, 5);
        paramMap.put("EM5", DataParseUtil.parseToStringList(em5));
        List<Long> mVol5 = IndicatorUtil.EMAn(hisVol, 5);
        paramMap.put("MVOL5", DataParseUtil.parseToStringList(mVol5));
        result.setParamMap(paramMap);
        return result;
    }

    @Override
    public StrategyResult exec(String code, IndicatorResult indicatorResult, TradeSystemContext tradeSystemContext) {
        Bar bar = tradeSystemContext.getDataCache().getcurrentBar().get(code);
        StrategyResult strategyResult = new StrategyResult();
        strategyResult.setCode(code);
        strategyResult.setStrategyCallType(StrategyCallType.NOTHING);

        Map<String, List<String>> paramMap = indicatorResult.getParamMap();
        if (paramMap == null){
            return strategyResult;
        }
        List<String> m5 = paramMap.get("M5");
        List<String> m10 = paramMap.get("M10");
        List<String> m30 = paramMap.get("M30");
        List<String> em5 = paramMap.get("EM5");
        List<String> mVol5 = paramMap.get("MVOL5");
        Long close = bar.getClose();
        Long vol = bar.getVolume();
        if (m5.size() > 2 && em5.size() > 2){
            boolean t1CrossT2 = IndicatorUtil.t1UpCrossT2(
                    Long.parseLong(m5.get(m5.size() - 1)), Long.parseLong(m5.get(m5.size() - 2)),
                    Long.parseLong(em5.get(em5.size() - 1)), Long.parseLong(em5.get(em5.size() - 2)),
                    true);
            if (t1CrossT2){
                Long m5Now = Long.valueOf(m5.get(m5.size()-1));
                Long mVol5Now = Long.valueOf(mVol5.get(mVol5.size()-1));
                Long m10Now = Long.valueOf(m10.get(m10.size()-1));
                Long m30Now = Long.valueOf(m30.get(m30.size()-1));
                if (close > m5Now && vol > mVol5Now && m5Now > m10Now){
                    strategyResult.setStrategyCallType(StrategyCallType.BUY);
                }
            }
            boolean t2CrossT1 = IndicatorUtil.t1UpCrossT2(
                    Long.parseLong(m5.get(m5.size() - 1)), Long.parseLong(m5.get(m5.size() - 2)),
                    Long.parseLong(em5.get(em5.size() - 1)), Long.parseLong(em5.get(em5.size() - 2)),
                    false);
            if (t2CrossT1){
                strategyResult.setStrategyCallType(StrategyCallType.SELL);
            }
        }

        strategyResult.setNumAround(1L);
        strategyResult.setPriceAround(100L);
        strategyResult.setPrice(bar.getClose());
        return strategyResult;
    }
}
